#define _GNU_SOURCE  // 启用GNU扩展，包括strdup函数
#include "server_functions.h"
#include <sys/time.h>  // 用于设置系统时间
#include <sys/statvfs.h>  // 用于获取文件系统信息
#include <errno.h>
#include <limits.h>

// 如果系统没有定义PATH_MAX，使用默认值
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif

// ping计数器静态变量
static int ping_count = 0;

/**
 * 格式化字节数为可读格式
 * @param bytes 字节数
 * @param buffer 输出缓冲区
 * @param buffer_size 缓冲区大小
 */
void format_bytes(unsigned long long bytes, char *buffer, size_t buffer_size) {
    const char *units[] = {"B", "KB", "MB", "GB", "TB"};
    int unit_index = 0;
    double size = (double)bytes;
    
    while (size >= 1024.0 && unit_index < 4) {
        size /= 1024.0;
        unit_index++;
    }
    
    if (unit_index == 0) {
        snprintf(buffer, buffer_size, "%llu %s", bytes, units[unit_index]);
    } else {
        snprintf(buffer, buffer_size, "%.2f %s", size, units[unit_index]);
    }
}

/**
 * 获取TF卡容量信息
 * @param mount_path TF卡挂载路径
 * @param total_bytes 输出总容量(字节)
 * @param free_bytes 输出剩余容量(字节) 
 * @param used_bytes 输出已使用容量(字节)
 * @param usage_percent 输出使用率(百分比)
 * @return 0: 成功, -1: 失败
 */
int get_tf_card_info(const char *mount_path, unsigned long long *total_bytes, 
                     unsigned long long *free_bytes, unsigned long long *used_bytes, 
                     double *usage_percent) {
    struct statvfs vfs;
    
    // 检查路径是否存在
    if (access(mount_path, F_OK) != 0) {
        return -1;
    }
    
    // 获取文件系统统计信息
    if (statvfs(mount_path, &vfs) != 0) {
        return -1;
    }
    
    // 计算容量信息
    *total_bytes = (unsigned long long)vfs.f_blocks * vfs.f_frsize;
    *free_bytes = (unsigned long long)vfs.f_bavail * vfs.f_frsize;
    *used_bytes = *total_bytes - *free_bytes;
    
    // 计算使用率
    if (*total_bytes > 0) {
        *usage_percent = (double)(*used_bytes) / (*total_bytes) * 100.0;
    } else {
        *usage_percent = 0.0;
    }
    
    return 0;
}

// 解析查询字符串
Param *parse_query_string(char *query, int *param_count) {
    if (!query || !param_count) return NULL;

    *param_count = 0;
    
    // 计算参数数量
    char *temp = strdup(query);
    char *token = strtok(temp, "&");
    while (token) {
        (*param_count)++;
        token = strtok(NULL, "&");
    }
    free(temp);
    
    if (*param_count == 0) return NULL;
    
    // 分配参数数组
    Param *params = (Param *)malloc(sizeof(Param) * (*param_count));
    if (!params) return NULL;
    
    // 解析每个参数
    temp = strdup(query);
    token = strtok(temp, "&");
    int i = 0;
    
    while (token && i < *param_count) {
        char *equal_sign = strchr(token, '=');
        if (equal_sign) {
            *equal_sign = '\0';
            params[i].name = strdup(token);
            params[i].value = strdup(equal_sign + 1);
        } else {
            params[i].name = strdup(token);
            params[i].value = strdup("");
        }
        i++;
        token = strtok(NULL, "&");
    }
    
    free(temp);
    return params;
}

// 释放参数数组
void free_params(Param *params, int param_count) {
    if (!params || param_count <= 0) return;
    
    for (int i = 0; i < param_count; i++) {
        free(params[i].name);
        free(params[i].value);
    }
    
    free(params);
}

// 处理CGI请求
void handle_cgi(SOCKET client_socket, const char *path, Param *params, int param_count) {
    if (!path) {
        send_json_response(client_socket, "{\"error\":\"Invalid CGI path\"}", 400);
        return;
    }
    
    // 简化的CGI处理，根据路径执行不同的功能
    if (strcmp(path, "/cgi/ping") == 0) {
        // 递增计数器
        ping_count++;
        // 返回带计数的响应
        char json_response[256];
        sprintf(json_response, "{\"response\":\"pong\",\"count\":%d}", ping_count);
        send_json_response(client_socket, json_response, 200);
    } else if (strcmp(path, "/cgi/echo") == 0) {
        char json_response[4096] = "{\"echo\":{";
        int first = 1;
        
        for (int i = 0; i < param_count; i++) {
            if (!first) {
                strcat(json_response, ",");
            }
            first = 0;
            sprintf(json_response + strlen(json_response), "\"%s\":\"%s\"", 
                    params[i].name, params[i].value);
        }
        
        strcat(json_response, "}}");
        send_json_response(client_socket, json_response, 200);
    } else if (strcmp(path, "/cgi/get_time") == 0) {
        time_t now = time(NULL);
        struct tm *time_info = localtime(&now);
        char time_str[64];
        strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", time_info);
        
        char json_response[256];
        sprintf(json_response, "{\"time\":\"%s\"}", time_str);
        send_json_response(client_socket, json_response, 200);
    } else if (strcmp(path, "/cgi/set_time") == 0) {
        // GET方式设置系统时间
        printf("[DEBUG] Processing set_time GET request\n");
        
        // 查找时间参数
        char *time_str = NULL;
        for (int i = 0; i < param_count; i++) {
            printf("[DEBUG] GET Parameter %d: %s = %s\n", i, params[i].name, params[i].value);
            if (strcmp(params[i].name, "time") == 0) {
                time_str = params[i].value;
                printf("[DEBUG] Found time parameter: %s\n", time_str);
                break;
            }
        }
        
        // 验证时间参数是否存在
        if (!time_str || strlen(time_str) == 0) {
            printf("[ERROR] Time parameter not found in GET request\n");
            char json_response[256];
            sprintf(json_response, 
                "{\"success\":false,\"error\":\"Time parameter is required. Format: YYYY-MM-DD HH:MM:SS\",\"method\":\"GET\"}");
            send_json_response(client_socket, json_response, 400);
        } else {
            // 解析时间字符串 (格式: YYYY-MM-DD HH:MM:SS)
            struct tm time_info = {0};
            printf("[DEBUG] Parsing GET time string: %s\n", time_str);
            if (sscanf(time_str, "%d-%d-%d %d:%d:%d", 
                       &time_info.tm_year, &time_info.tm_mon, &time_info.tm_mday, 
                       &time_info.tm_hour, &time_info.tm_min, &time_info.tm_sec) != 6) {
                printf("[ERROR] Failed to parse GET time format\n");
                char json_response[256];
                sprintf(json_response, 
                    "{\"success\":false,\"error\":\"Invalid time format. Use: YYYY-MM-DD HH:MM:SS\",\"method\":\"GET\"}");
                send_json_response(client_socket, json_response, 400);
            } else {
                printf("[DEBUG] Parsed GET time: %04d-%02d-%02d %02d:%02d:%02d\n", 
                       time_info.tm_year, time_info.tm_mon, time_info.tm_mday,
                       time_info.tm_hour, time_info.tm_min, time_info.tm_sec);
                
                // 验证时间参数是否有效
                if (time_info.tm_year < 2000 || time_info.tm_mon < 1 || time_info.tm_mon > 12 || 
                    time_info.tm_mday < 1 || time_info.tm_mday > 31 || 
                    time_info.tm_hour < 0 || time_info.tm_hour > 23 || 
                    time_info.tm_min < 0 || time_info.tm_min > 59 || 
                    time_info.tm_sec < 0 || time_info.tm_sec > 59) {
                    printf("[ERROR] Invalid GET time values detected\n");
                    char json_response[256];
                    sprintf(json_response, 
                        "{\"success\":false,\"error\":\"Invalid time values\",\"method\":\"GET\"}");
                    send_json_response(client_socket, json_response, 400);
                } else {
                    printf("[DEBUG] GET time validation passed\n");
                    
                    // 调整tm_year和tm_mon的值
                    time_info.tm_year -= 1900;
                    time_info.tm_mon -= 1;
                    printf("[DEBUG] Adjusted GET time structure: year=%d, mon=%d\n", time_info.tm_year, time_info.tm_mon);
                    
                    // 转换为time_t
                    time_t new_time = mktime(&time_info);
                    if (new_time == -1) {
                        printf("[ERROR] mktime() failed for GET request\n");
                        char json_response[256];
                        sprintf(json_response, 
                            "{\"success\":false,\"error\":\"Failed to convert time\",\"method\":\"GET\"}");
                        send_json_response(client_socket, json_response, 500);
                    } else {
                        printf("[DEBUG] Converted GET time to time_t: %ld\n", (long)new_time);
                        
                        // 设置系统时间
                        struct timeval tv;
                        tv.tv_sec = new_time;
                        tv.tv_usec = 0;
                        printf("[DEBUG] Attempting to set system time via GET\n");
                        
                        if (settimeofday(&tv, NULL) == -1) {
                            printf("[ERROR] GET settimeofday() failed: %s\n", strerror(errno));
                            char json_response[256];
                            sprintf(json_response, 
                                "{\"success\":false,\"error\":\"Permission denied or system error\",\"method\":\"GET\"}");
                            send_json_response(client_socket, json_response, 500);
                        } else {
                            printf("[DEBUG] System time set successfully via GET\n");
                            
                            // 格式化返回的时间字符串
                            char formatted_time[64];
                            struct tm *set_time_info = localtime(&new_time);
                            strftime(formatted_time, sizeof(formatted_time), "%Y-%m-%d %H:%M:%S", set_time_info);
                            printf("[DEBUG] Formatted GET response time: %s\n", formatted_time);
                            
                            // 返回成功响应
                            char json_response[256];
                            sprintf(json_response, 
                                "{\"success\":true,\"message\":\"System time updated successfully via GET\",\"time\":\"%s\",\"method\":\"GET\"}",
                                formatted_time);
                            printf("[DEBUG] Sending GET time response: %s\n", json_response);
                            send_json_response(client_socket, json_response, 200);
                        }
                    }
                }
            }
        }
    } else if (strcmp(path, "/cgi/get_tf_info") == 0) {
        // 默认TF卡挂载路径，可以通过参数指定
        const char *mount_path = "/mnt";
        
        // 检查是否有path参数指定挂载路径
        for (int i = 0; i < param_count; i++) {
            if (strcmp(params[i].name, "path") == 0 && strlen(params[i].value) > 0) {
                mount_path = params[i].value;
                break;
            }
        }
        
        unsigned long long total_bytes, free_bytes, used_bytes;
        double usage_percent;
        
        if (get_tf_card_info(mount_path, &total_bytes, &free_bytes, &used_bytes, &usage_percent) == 0) {
            // 格式化容量信息
            char total_str[64], free_str[64], used_str[64];
            format_bytes(total_bytes, total_str, sizeof(total_str));
            format_bytes(free_bytes, free_str, sizeof(free_str));
            format_bytes(used_bytes, used_str, sizeof(used_str));
            
            // 构建JSON响应
            char json_response[1024];
            sprintf(json_response, 
                "{"
                "\"success\":true,"
                "\"mount_path\":\"%s\","
                "\"total_bytes\":%llu,"
                "\"free_bytes\":%llu,"
                "\"used_bytes\":%llu,"
                "\"usage_percent\":%.2f,"
                "\"total_formatted\":\"%s\","
                "\"free_formatted\":\"%s\","
                "\"used_formatted\":\"%s\""
                "}",
                mount_path, total_bytes, free_bytes, used_bytes, usage_percent,
                total_str, free_str, used_str);
            
            send_json_response(client_socket, json_response, 200);
        } else {
            // 错误响应
            char json_response[256];
            sprintf(json_response, 
                "{"
                "\"success\":false,"
                "\"error\":\"Failed to get TF card info\","
                "\"mount_path\":\"%s\""
                "}", mount_path);
            send_json_response(client_socket, json_response, 500);
        }
    } else if (strcmp(path, "/cgi/ota_status") == 0) {
        // 获取OTA升级状态
        char json_response[512];
        
        // 检查上传目录是否存在
        struct stat st = {0};
        int upload_dir_exists = (stat(UPLOAD_DIR, &st) == 0 && S_ISDIR(st.st_mode));
        
        // 获取上传目录中的文件数量
        int file_count = 0;
        if (upload_dir_exists) {
            DIR *dir = opendir(UPLOAD_DIR);
            if (dir) {
                struct dirent *entry;
                while ((entry = readdir(dir)) != NULL) {
                    if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
                        file_count++;
                    }
                }
                closedir(dir);
            }
        }
        
        sprintf(json_response,
            "{"
            "\"success\":true,"
            "\"upload_dir_exists\":%s,"
            "\"upload_dir\":\"%s\","
            "\"file_count\":%d,"
            "\"max_upload_size\":%d,"
            "\"supported_extensions\":[\"bin\",\"img\",\"tar\",\"gz\",\"zip\"]"
            "}",
            upload_dir_exists ? "true" : "false",
            UPLOAD_DIR,
            file_count,
            MAX_UPLOAD_SIZE);
        
        send_json_response(client_socket, json_response, 200);
    } else if (strcmp(path, "/cgi/ota_list") == 0) {
        // 列出上传的OTA文件
        struct stat st = {0};
        if (stat(UPLOAD_DIR, &st) != 0 || !S_ISDIR(st.st_mode)) {
            send_json_response(client_socket, 
                "{\"success\":false,\"error\":\"Upload directory not found\"}", 404);
            return;
        }
        
        DIR *dir = opendir(UPLOAD_DIR);
        if (!dir) {
            send_json_response(client_socket, 
                "{\"success\":false,\"error\":\"Cannot open upload directory\"}", 500);
            return;
        }
        
        char json_response[4096] = "{\"success\":true,\"files\":[";
        struct dirent *entry;
        int first = 1;
        int file_count = 0;
        
        while ((entry = readdir(dir)) != NULL) {
            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
                continue;
            }
            
            char file_path[512];
            sprintf(file_path, "%s/%s", UPLOAD_DIR, entry->d_name);
            
            struct stat file_stat;
            if (stat(file_path, &file_stat) == 0 && S_ISREG(file_stat.st_mode)) {
                if (!first) {
                    strcat(json_response, ",");
                }
                first = 0;
                file_count++;
                
                // 格式化文件修改时间
                char time_str[64];
                struct tm *time_info = localtime(&file_stat.st_mtime);
                strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", time_info);
                
                sprintf(json_response + strlen(json_response),
                    "{"
                    "\"name\":\"%s\","
                    "\"size\":%ld,"
                    "\"modified\":\"%s\","
                    "\"path\":\"%s\""
                    "}",
                    entry->d_name,
                    file_stat.st_size,
                    time_str,
                    file_path);
            }
        }
        
        closedir(dir);
        sprintf(json_response + strlen(json_response), "],\"file_count\":%d}", file_count);
        
        send_json_response(client_socket, json_response, 200);
    } else if (strcmp(path, "/cgi/ota_install") == 0) {
        // 执行OTA升级
        char *filename = NULL;
        
        // 获取文件名参数
        for (int i = 0; i < param_count; i++) {
            if (strcmp(params[i].name, "file") == 0 && strlen(params[i].value) > 0) {
                filename = params[i].value;
                break;
            }
        }
        
        if (!filename) {
            send_json_response(client_socket, 
                "{\"success\":false,\"error\":\"File parameter is required\"}", 400);
            return;
        }
        
        // 验证文件名安全性
        if (!validate_filename(filename)) {
            send_json_response(client_socket, 
                "{\"success\":false,\"error\":\"Invalid filename\"}", 400);
            return;
        }
        
        // 构建文件路径
        char file_path[512];
        sprintf(file_path, "%s/%s", UPLOAD_DIR, filename);
        
        // 检查文件是否存在
        struct stat file_stat;
        if (stat(file_path, &file_stat) != 0 || !S_ISREG(file_stat.st_mode)) {
            send_json_response(client_socket, 
                "{\"success\":false,\"error\":\"File not found\"}", 404);
            return;
        }
        
        // 模拟OTA升级过程（在实际应用中，这里会调用实际的升级命令）
        printf("[INFO] Starting OTA upgrade with file: %s\n", filename);
        
        // 这里可以添加实际的OTA升级逻辑，例如：
        // 1. 验证文件的校验和和签名
        // 2. 停止其他应用服务
        // 3. 执行升级脚本或命令
        // 4. 重启系统
        
        // 模拟升级成功
        char json_response[512];
        sprintf(json_response,
            "{"
            "\"success\":true,"
            "\"message\":\"OTA upgrade initiated successfully\","
            "\"filename\":\"%s\","
            "\"file_size\":%ld,"
            "\"status\":\"upgrade_started\","
            "\"note\":\"System will reboot automatically after upgrade\""
            "}",
            filename,
            file_stat.st_size);
        
        send_json_response(client_socket, json_response, 200);
        
        // 在实际应用中，这里可能需要延迟一段时间后关闭服务器并执行升级
    } else if (strcmp(path, "/cgi/ota_cleanup") == 0) {
        // 清理上传的文件
        struct stat st = {0};
        if (stat(UPLOAD_DIR, &st) != 0 || !S_ISDIR(st.st_mode)) {
            send_json_response(client_socket, 
                "{\"success\":false,\"error\":\"Upload directory not found\"}", 404);
            return;
        }
        
        DIR *dir = opendir(UPLOAD_DIR);
        if (!dir) {
            send_json_response(client_socket, 
                "{\"success\":false,\"error\":\"Cannot open upload directory\"}", 500);
            return;
        }
        
        int deleted_count = 0;
        struct dirent *entry;
        
        while ((entry = readdir(dir)) != NULL) {
            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
                continue;
            }
            
            char file_path[512];
            sprintf(file_path, "%s/%s", UPLOAD_DIR, entry->d_name);
            
            if (unlink(file_path) == 0) {
                deleted_count++;
                printf("[INFO] Deleted: %s\n", file_path);
            } else {
                printf("[ERROR] Failed to delete: %s - %s\n", file_path, strerror(errno));
            }
        }
        
        closedir(dir);
        
        char json_response[256];
        sprintf(json_response,
            "{"
            "\"success\":true,"
            "\"message\":\"Cleanup completed\","
            "\"deleted_files\":%d"
            "}",
            deleted_count);
        
        send_json_response(client_socket, json_response, 200);
    } else {
        send_json_response(client_socket, "{\"error\":\"Unknown CGI function\"}", 404);
    }
}

// 获取文件内容
char *get_file_content(const char *file_path) {
    if (!file_path) return NULL;

    FILE *file = fopen(file_path, "rb");
    if (!file) return NULL;

    // 获取文件大小
    fseek(file, 0, SEEK_END);
    long file_size = ftell(file);
    fseek(file, 0, SEEK_SET);

    // 读取文件内容
    char *content = (char *)malloc(file_size + 1);
    if (!content) {
        fclose(file);
        return NULL;
    }
    
    fread(content, 1, file_size, file);
    content[file_size] = '\0';
    
    fclose(file);
    return content;
}

// 获取文件的MIME类型
char *get_mime_type(const char *file_path) {
    if (!file_path) return "application/octet-stream";

    const char *ext = strrchr(file_path, '.');
    if (!ext) return "application/octet-stream";
    
    if (strcmp(ext, ".html") == 0 || strcmp(ext, ".htm") == 0) {
        return "text/html";
    } else if (strcmp(ext, ".css") == 0) {
        return "text/css";
    } else if (strcmp(ext, ".js") == 0) {
        return "application/javascript";
    } else if (strcmp(ext, ".json") == 0) {
        return "application/json";
    } else if (strcmp(ext, ".png") == 0) {
        return "image/png";
    } else if (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".jpeg") == 0) {
        return "image/jpeg";
    } else if (strcmp(ext, ".gif") == 0) {
        return "image/gif";
    } else if (strcmp(ext, ".txt") == 0) {
        return "text/plain";
    } else {
        return "application/octet-stream";
    }
}